package com.baike.controller;


import com.alibaba.fastjson.JSON;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.baike.data.RedisName;
import com.baike.data.Result;
import com.baike.em.ConstantEnum;
import com.baike.entity.TbLessonCatalogue;
import com.baike.service.impl.TbLessonCatalogueServiceImpl;
import com.baike.vo.CatalogueVoClass;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.annotations.*;
import it.sauronsoftware.jave.EncoderException;
import org.apache.commons.io.FileUtils;
import org.apache.http.entity.ContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.MultimediaInfo;


import java.io.*;
import java.util.*;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author lbs
 * @since 2021-10-31
 */
@RestController
@RequestMapping("lessonCatalogueController")
@Api("课程目录管理中心")
public class TbLessonCatalogueController {

    @Autowired
    private TbLessonCatalogueServiceImpl catalogueService;
    @Autowired
    private RedisTemplate redisTemplate;

    @PostMapping(headers="content-type=multipart/form-data")
    @ApiOperation("课程目录增加")
    @ApiImplicitParams({
            @ApiImplicitParam(name="id",value = "目录ID",paramType = "query"),
            @ApiImplicitParam(name="lessonId",value = "课程ID",required = true,paramType = "query"),
            @ApiImplicitParam(name="pid",value = "目录父ID",required = true,paramType = "query"),
            @ApiImplicitParam(name="catalogueName",value = "目录名称",required = true,paramType = "query"),
    })
    public Result postCatalogue(TbLessonCatalogue catalogue, @ApiParam(name = "video",value = "视频",required = true) MultipartFile video){
        StringRedisSerializer serializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jack = new Jackson2JsonRedisSerializer(Object.class);
        redisTemplate.setHashKeySerializer(serializer);
        redisTemplate.setKeySerializer(serializer);
        redisTemplate.setValueSerializer(jack);
        redisTemplate.setHashValueSerializer(jack);


        // 非空判断
        if(Objects.nonNull(catalogue.getLessonId()) && Objects.nonNull(catalogue.getPid()) && Objects.nonNull(catalogue.getCatalogueName())){
            if(Objects.nonNull(video)){
                //将视频上传至阿里服务器并返回视频地址
                Map<String, String> map = upLoadFile(video);
                String videoUrl = map.get("videoUrl");
                catalogue.setVideoUrl(videoUrl);

                //获取视频时长
                Encoder encoder = new Encoder();
                long videoLength = 0;
                File file = new File(video.getOriginalFilename());
                //MultipartFile转File
                try {
                    FileUtils.copyInputStreamToFile(video.getInputStream(), file);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    MultimediaInfo info = encoder.getInfo(file);
                    videoLength = info.getDuration();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                catalogue.setVideoLength(videoLength);
            }
            boolean b = catalogueService.save(catalogue);
            if(b){
                // 删除redis缓存
                redisTemplate.boundHashOps(RedisName.CATALOGUE_PARENT_NAME).delete(RedisName.CATALOGUE_CHILDREN_NAME + catalogue.getLessonId());
                return Result.build(ConstantEnum.SUCCESS);
            }
            return Result.build(ConstantEnum.ERROR);

        }
        return Result.build(ConstantEnum.NULL_DATA_PARAMETER);


    }

    //上传视频
    public Map<String,String> upLoadFile(@RequestParam(value = "myFile") MultipartFile myFile) {
        // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1（杭州）为例，
        // Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
        String http = "http://";
        String endpoint = "oss-cn-beijing.aliyuncs.com";
        String buketName = "pengpeng-shop";
        // 阿里云账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维，请登录RAM控制台创建RAM用户。
        String accessKeyId = "LTAI5t9QoZxwEzGHBPDQHJBu";
        String accessKeySecret = "mJOOC6yd3Qmm96Jx7osQV60AxrtRxK";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // 填写网络流地址。
        InputStream inputStream = null;
        try {
            inputStream = myFile.getInputStream();

        } catch (IOException e) {
            e.printStackTrace();
        }

        String fileName = myFile.getOriginalFilename();
        fileName = UUID.randomUUID() + fileName.substring(fileName.lastIndexOf("."));

        // 依次填写Bucket名称（例如examplebucket）和Object完整路径（例如exampledir/exampleobject.txt）。Object完整路径中不能包含Bucket名称。
        ossClient.putObject(buketName, fileName, inputStream);

        String url = http + buketName+ "." + endpoint + "/" + fileName;
        // 关闭OSSClient。
        ossClient.shutdown();

        Map<String,String> map = new HashMap<>();
        map.put("videoUrl", url);
        return map;
    }

    @DeleteMapping
    @ApiOperation("根据目录id数组删除一条多条目录 或者 根据课程id数组 删除一个多个课程目录")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "目录id数组",name = "ids",required = false,paramType = "query"),
            @ApiImplicitParam(value = "课程id数组",name = "lessonIds",required = false,paramType = "query"),
    })
    public Result delCatalogue(@RequestParam(value = "ids",required = false)Long[] ids
            , @RequestParam(value = "lessonIds",required = false)Long[] lessonIds){

        StringRedisSerializer serializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jack = new Jackson2JsonRedisSerializer(Object.class);
        redisTemplate.setHashKeySerializer(serializer);
        redisTemplate.setKeySerializer(serializer);
        redisTemplate.setValueSerializer(jack);
        redisTemplate.setHashValueSerializer(jack);

        // 参数判断 两者都为空 返回错误信息
        if(Objects.nonNull(ids) == true || Objects.nonNull(lessonIds) == true){
            // 定义一个当目录ids 不为空时 查询这些目录的课程ids
            Collection<TbLessonCatalogue> listByIds = null;
            // 定义条件构造器
            LambdaQueryWrapper<TbLessonCatalogue> wrapper = Wrappers.<TbLessonCatalogue>lambdaQuery();
            if (Objects.nonNull(ids)){
                wrapper.in(Objects.nonNull(ids), TbLessonCatalogue::getId, Arrays.asList(ids));
                // 获取课程id
                listByIds = catalogueService.listByIds(Arrays.asList(ids));
            }
            if(Objects.nonNull(lessonIds) == true){
                wrapper.in(Objects.nonNull(lessonIds), TbLessonCatalogue::getLessonId, Arrays.asList(lessonIds));
            }

            boolean b = catalogueService.remove(wrapper);
            if(b){
               // 如果目录ids 不为空 查询所有的目录信息 删除对于的课程缓存
                if(Objects.nonNull(ids)){

                    // 循环删除redis中的 课程目录缓存
                    listByIds.forEach(c -> redisTemplate.boundHashOps(RedisName.CATALOGUE_PARENT_NAME).delete(RedisName.CATALOGUE_CHILDREN_NAME + c.getLessonId()));
                }
                //如果课程ids 不为空
                if(Objects.nonNull(lessonIds)){
                    // 循环删除redis中的 课程目录缓存
                    Arrays.asList(lessonIds).forEach(i -> redisTemplate.boundHashOps(RedisName.CATALOGUE_PARENT_NAME).delete(RedisName.CATALOGUE_CHILDREN_NAME + i));
                }

                return Result.build(ConstantEnum.SUCCESS);
            }else {
                return Result.build(ConstantEnum.ERROR);
            }
        }
        return Result.build(ConstantEnum.NULL_DATA_PARAMETER);
    }

    @PutMapping
    @ApiOperation("根据传来的 一条目录信息 修改数据")
    @ApiImplicitParam(value = "课程目录实体数据",name = "catalogue",required = true,paramType = "body")
    public Result putCatlogue(@RequestBody TbLessonCatalogue catalogue){
        StringRedisSerializer serializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jack = new Jackson2JsonRedisSerializer(Object.class);
        redisTemplate.setHashKeySerializer(serializer);
        redisTemplate.setKeySerializer(serializer);
        redisTemplate.setValueSerializer(jack);
        redisTemplate.setHashValueSerializer(jack);

        if(Objects.nonNull(catalogue.getId())  && Objects.nonNull(catalogue.getLessonId())
                && Objects.nonNull(catalogue.getPid()) && Objects.nonNull(catalogue.getCatalogueName())){
            boolean b = catalogueService.updateById(catalogue);
            if(b){
                // 修改数据成功 删除 redis缓存
                redisTemplate.boundHashOps(RedisName.CATALOGUE_PARENT_NAME).delete(RedisName.CATALOGUE_CHILDREN_NAME + catalogue.getLessonId());
                return Result.build(ConstantEnum.SUCCESS);
            }else {
                return Result.build(ConstantEnum.ERROR);
            }
        }
        return Result.build(ConstantEnum.NULL_DATA_PARAMETER);
    }

    @PostMapping("findCatalogueByIdOrLessonId")
    @ApiOperation("根据目录id查询一条数据 或者根据课程id 查询课程的整个目录表")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "目录Id",name = "id",required = false,paramType = "query"),
            @ApiImplicitParam(value = "课程Id",name = "lessonId",required = false,paramType = "query")
    })
    public Result findCatalogueByIdOrLessonId(@RequestParam(value = "id",required = false)Long id , @RequestParam(value = "lessonId",required = false)Long lessonId){

        StringRedisSerializer serializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jack = new Jackson2JsonRedisSerializer(Object.class);
        redisTemplate.setHashKeySerializer(serializer);
        redisTemplate.setKeySerializer(serializer);
        redisTemplate.setValueSerializer(jack);
        redisTemplate.setHashValueSerializer(jack);
        // 非空判断
        if(Objects.nonNull(id) == true || Objects.nonNull(lessonId) == true){
            // 如果目录id 不为空返回单挑目录
            if(Objects.nonNull(id)){
                TbLessonCatalogue catalogueServiceById = catalogueService.getById(id);
                if(Objects.nonNull(catalogueServiceById)){
                    return Result.build(ConstantEnum.SUCCESS).setResult(catalogueServiceById);
                }else {
                    return Result.build(ConstantEnum.NULL_DATA);
                }
            }
            //否则用课程id 查询整个课程的目录表
            BoundHashOperations hashOps = redisTemplate.boundHashOps(RedisName.CATALOGUE_PARENT_NAME);
            // 判断redis缓存是否有这个数据
            if(hashOps.hasKey(RedisName.CATALOGUE_CHILDREN_NAME + lessonId)){
                String listStr = (String)hashOps.get(RedisName.CATALOGUE_CHILDREN_NAME + lessonId);
                List<CatalogueVoClass> catalogueVoClassList = JSON.parseArray(listStr, CatalogueVoClass.class);
                // 返回数据
                return Result.build(ConstantEnum.SUCCESS).setResult(catalogueVoClassList);
            }else {
                // 缓存没有 从数据库查询
                List<CatalogueVoClass> catalogueList = catalogueService.findCatalogueByLessonId(lessonId);
                // 根据查询的数据状态 放入缓存
                if(catalogueList.size() > 0){
                    hashOps.put(RedisName.CATALOGUE_CHILDREN_NAME + lessonId,JSON.toJSON(catalogueList).toString());
                    return Result.build(ConstantEnum.SUCCESS).setResult(catalogueList);
                }else {
                    return Result.build(ConstantEnum.NULL_DATA).setResult(catalogueList);
                }
            }


        }
        return Result.build(ConstantEnum.NULL_DATA_PARAMETER);
    }


}
